package com.pmcc.core.service;


import com.pmcc.core.config.security.JwtUser;
import com.pmcc.core.entity.security.Employee;
import com.pmcc.core.entity.security.Menu;
import com.pmcc.core.entity.security.Role;
import com.pmcc.core.enums.ModuleType;
import com.pmcc.core.repository.EmployeeRepository;
import com.pmcc.core.repository.MenuRepository;
import com.pmcc.core.vo.CurrentUserVO;
import com.pmcc.core.vo.MenuComboVO;
import com.pmcc.core.vo.MenuVO;
import com.pmcc.utils.BeanUtils;
import com.pmcc.utils.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by syk on 17/7/6.
 */
@Slf4j
@Service
@Transactional
public class MenuService {

    @Autowired
    private MenuRepository menuRepository;

    @Autowired
    EmployeeRepository employeeRepository;

    /**
     * 查询列表
     *
     * @return
     */
    public ResultBean queryList() {
        ResultBean resultBean = new ResultBean(ResultBean.SUCCESS);
        List<Menu> menuList = menuRepository.findByOrderBySortNo();

        List<Menu> firstLevel = new ArrayList<>();
        Map<String, List<Menu>> secondLevel = new HashMap<>();
        for (Menu menu : menuList) {
            if(menu.getParentId().equals("-1")) {
                firstLevel.add(menu);
                continue;
            }

            if(!secondLevel.containsKey(menu.getParentId())){
                secondLevel.put(menu.getParentId(), new ArrayList<>());
            }
            secondLevel.get(menu.getParentId()).add(menu);
        }

        List<MenuVO> resultList = new ArrayList<>();
        for (Menu menu : firstLevel) {
            MenuVO vo = new MenuVO();
            BeanUtils.copyProperties(menu, vo);
            List<Menu> list = secondLevel.getOrDefault(menu.getId(), new ArrayList<>());
            for (Menu model : list) {
                MenuVO subVo = new MenuVO();
                BeanUtils.copyProperties(model, subVo);
                subVo.setParentName(menu.getName());
                if(vo.getChildren()==null){
                    vo.setChildren(new ArrayList<>());
                }
                vo.getChildren().add(subVo);
            }
            resultList.add(vo);
        }

        resultBean.setRows(resultList);
        return resultBean;
    }


    /**
     * 新增菜单
     *
     * @param model
     * @return
     */
    public ResultBean saveOrUpdate(Menu model) {
        ResultBean resultBean = new ResultBean(ResultBean.SUCCESS);
        if(StringUtils.isEmpty(model.getId())){
            if (StringUtils.isEmpty(model.getParentId())) {
                model.setParentId("-1");
            } else {
                Menu parentMenu = menuRepository.findOne(model.getParentId());
                //如果徐那种增加的父树根类型是叶子，则改为根
                if (parentMenu != null && parentMenu.getLeaf()) {
                    parentMenu.setLeaf(false);
                    menuRepository.save(parentMenu);
                }
            }
            model.setCreateTime(new Date());
            model.setModuleType(ModuleType.MENU);
            model.setLeaf(true);
            model.setDelFlag("0");
            menuRepository.save(model);
            resultBean.setResultDesc("新增成功！");
        }else {
            Menu oldMenu = menuRepository.findOne(model.getId());
            oldMenu.setCode(model.getCode());
            oldMenu.setName(model.getName());
            oldMenu.setIcon(model.getIcon());
            oldMenu.setPath(model.getPath());
            oldMenu.setSortNo(model.getSortNo());
            resultBean.setResultDesc("修改成功！");
        }
        return resultBean;
    }

    /**
     * 删除
     * 角色与菜单级联 角色为主  如果角色与菜单存在关系 删除角色的同时可以将关系删除
     * 但是 删除菜单并不会同时删除角色与菜单的关系 所以 有了下面的删除逻辑
     *
     * @param id
     * @return
     */
    public void delete(String id) {
        List<Menu> list = menuRepository.findByParentId(id);
        if (list != null && list.size() > 0) {
            for (Menu menu : list) {
                if(menu.getRoleList()!=null && menu.getRoleList().size()>0){
                    for (Role role : menu.getRoleList()) {
                        role.getMenuSet().remove(menu);
                    }
                }
                menuRepository.delete(menu);
            }
        }
        Menu obj = menuRepository.findOne(id);
        if(obj.getRoleList()!=null && obj.getRoleList().size()>0){
            for (Role role : obj.getRoleList()) {
                role.getMenuSet().remove(obj);
            }
        }
        menuRepository.delete(id);
    }


    public CurrentUserVO getCurrentUser() {
        JwtUser jwtUser = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Employee employee = employeeRepository.findOne(jwtUser.getId());

        CurrentUserVO currentUserVO = new CurrentUserVO();
        currentUserVO.setId(employee.getId());
        currentUserVO.setUsername(employee.getUsername());
        currentUserVO.setAvatar(employee.getAvatar());
        currentUserVO.setAddress(employee.getAddress());
        currentUserVO.setName(employee.getUserCName());
        currentUserVO.setMobile(employee.getMobile());
        currentUserVO.setEmail(employee.getEmail());
        currentUserVO.setType(employee.getType());
        currentUserVO.setEnabled(employee.isEnabled());
        currentUserVO.setOrgId(employee.getOrganization().getId());
        currentUserVO.setOrgName(employee.getOrganization().getName());

        if(employee.getRoleList()==null || employee.getRoleList().size()==0){
            currentUserVO.setMenuData(new ArrayList<>());
            return currentUserVO;
        }

        List<Role> roleList = employee.getRoleList();
        List<Menu> menuList = new ArrayList<>();
        for (Role role : roleList) {
            menuList.addAll(role.getMenuSet());
        }
        Set<String> filterList = new HashSet<>();
        List<Menu> firstLevel = new ArrayList<>();
        Map<String, List<Menu>> secondLevel = new HashMap<>();
        for (Menu menu : menuList) {
            if(filterList.contains(menu.getId()))
                continue;
            filterList.add(menu.getId());
            if(menu.getParentId().equals("-1")) {
                firstLevel.add(menu);
                continue;
            }

            if(!secondLevel.containsKey(menu.getParentId())){
                secondLevel.put(menu.getParentId(), new ArrayList<>());
            }
            secondLevel.get(menu.getParentId()).add(menu);
        }

        firstLevel.sort(Comparator.comparingInt(Menu::getSortNo));


        List<MenuComboVO> resultList = new ArrayList<>();
        for (Menu menu : firstLevel) {
            MenuComboVO vo = new MenuComboVO(menu);
            List<Menu> list = secondLevel.get(menu.getId());
            if (list != null && list.size() > 0) {
                list.sort(Comparator.comparingInt(Menu::getSortNo));
                for (Menu model : list) {
                    MenuComboVO subVo = new MenuComboVO(model);
                    vo.getChildren().add(subVo);
                }
            }
            resultList.add(vo);
        }
        currentUserVO.setMenuData(resultList);
        return currentUserVO;
    }
}
